package org.ws.httphelper.support.parser.field.operator;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.DomSerializer;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.ws.httphelper.model.field.ParseField;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XPathParseOperator extends AbstractParseOperator<Object> {

    private HtmlCleaner hc = new HtmlCleaner();
    private XPath xPath = XPathFactory.newInstance().newXPath();

    @Override
    public String parseString(String body, ParseField parseField) throws Exception {
        Document dom = clearUpDom(body);
        return xPath.evaluate(parseField.getParseExpression(),dom);
    }

    @Override
    public List parseList(String body, ParseField listFieldInfo) throws Exception {
        Document dom = clearUpDom(body);
        return evaluateList(listFieldInfo,dom);
    }

    @Override
    public Map parseMap(String body, ParseField mapFieldInfo) throws Exception {
        Document dom = clearUpDom(body);
        return evaluateMap(mapFieldInfo,dom);
    }

    private Document clearUpDom(String body) throws Exception {
        TagNode tagNode = hc.clean(body);
        Document dom = new DomSerializer(new CleanerProperties()).createDOM(tagNode);
        return dom;
    }

    @Override
    protected String evaluateString(ParseField parseField, Object item) throws Exception {
        return xPath.evaluate(parseField.getParseExpression(),item);
    }

    @Override
    protected List evaluateList(ParseField parseField, Object item) throws Exception {
        // 解析表达式
        String parseExpression = parseField.getParseExpression();
        // list类型必须从当前表达式获取列表
        NodeList nodeList = (NodeList)xPath.evaluate(parseExpression,item, XPathConstants.NODESET);
        List resultList = new ArrayList();
        if (nodeList != null) {
            // 有下级属性-》列表项是对象
            if(parseField.hasChild()){
                List<ParseField> childFieldList = parseField.getChildFieldInfoList();
                for (int i = 0; i < nodeList.getLength(); i++) {
                    // 从列表项获取下级对象属性
                    Node node = nodeList.item(i);
                    Map map = new HashMap();
                    evaluateChild(childFieldList,node,map);
                    resultList.add(map);
                }
            }
            else {
                // String列表项
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Node node = nodeList.item(i);
                    if(node != null){
                        resultList.add(node.getTextContent());
                    }
                }
            }
        }
        return resultList;
    }

    @Override
    protected Map evaluateMap(ParseField parseField, Object item) throws Exception {
        // 解析表达式
        String parseExpression = parseField.getParseExpression();
        Node node = (Node) xPath.evaluate(parseExpression,item, XPathConstants.NODE);
        // 对象必须有下级属性
        if(parseField.hasChild()){
            Map map = new HashMap();
            List<ParseField> childFieldList = parseField.getChildFieldInfoList();
            evaluateChild(childFieldList,node,map);
            return map;
        }
        return null;
    }
}
